package perform.event;

import java.sql.Connection;
import java.sql.SQLException;

import perform.Caretaker;
import perform.connection.ConnectionManager;
import perform.event.LoadEvent.LoadType;
import perform.lazy.PerformLoader;
import perform.lazy.PerformUpdater;
import perform.lazy.impl.ExtendedLoader;
import perform.lazy.impl.ExtendedUpdater;
import perform.lazy.impl.SimpleLoader;
import perform.lazy.impl.SimpleUpdater;
import perform.type.Type;

public class PerformEventHandler {

	private static ConnectionManager pool;

	private PerformLoader loader;
	private PerformUpdater updater;

	public PerformEventHandler() {
		if(Caretaker.getProperty("writeSQL").equals("true")){
			loader = new ExtendedLoader();
			updater = new ExtendedUpdater();
		} else {
			loader = new SimpleLoader();
			updater = new SimpleUpdater();
		}
	}

	public void handleLoadEvent(LoadEvent event) {
		try {
			Connection connection = pool.getConnection();
			LoadType loadType = event.getLoadType();
			switch (loadType) {
			case LOAD_M2M:
				loader.loadManyToMany(event, connection);
				break;
			case LOAD_M2O:
				loader.loadManyToOne(event, connection);
				break;
			case LOAD_O2M:
				loader.loadOneToMany(event, connection);
				break;
			case LOAD_O2O:
				loader.loadOneToOne(event, connection);
				break;
			default:
				break;
			}
			connection.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public <T extends Type> void handleAddEvent(UpdateEvent<T> event) {
		try {
			Connection connection = pool.getConnection();
			try {
				if (event.getTarget() != null) {
					updater.addManyToMany(event.getSource(),
							event.getSourceField(), event.getTarget(),
							connection);
				} else {
					for (int i = 0; i < event.getTargets().size(); i++) {
						updater.addManyToMany(event.getSource(),
								event.getSourceField(),
								event.getTargets().get(i), connection);
					}
				}
				connection.commit();
			} catch (Exception e) {
				if (e instanceof SQLException) {
					connection.rollback();
				}
				connection.close();
				throw e;
			}
			connection.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public <T extends Type> void handleRemoveEvent(UpdateEvent<T> event) {
		try {
			Connection connection = pool.getConnection();
			try {
				if (event.getTarget() != null) {
					updater.removeManyToMany(event.getSource(),
							event.getSourceField(), event.getTarget(),
							connection);
				} else {
					for (int i = 0; i < event.getTargets().size(); i++) {
						updater.removeManyToMany(event.getSource(),
								event.getSourceField(),
								event.getTargets().get(i), connection);
					}
				}
				connection.commit();
			} catch (Exception e) {
				if (e instanceof SQLException) {
					connection.rollback();
				}
				connection.close();
				throw e;
			}
			connection.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void setPool(ConnectionManager pool) {
		PerformEventHandler.pool = pool;
	}

}
